package cn.bitkit.base.util;

import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.StringJoiner;


/**
 * @author changbo
 * 
 */
@Slf4j
public class StringUtil {
	
	public static final String ENCODING_SET = "UTF-8";

	public static boolean hasValue(Object obj){
        return obj != null && !obj.toString().trim().isEmpty();
    }

	public static boolean allHasValue(Object... array){
		for(Object obj : array) {
			if(isEmpty(obj)) {
				return false;
			}
		}
		return true;
	}
	
	public static boolean isEmpty(Object obj){
		return !hasValue(obj);
	}

	public static boolean allIsEmpty(Object... array){
		for(Object obj : array) {
			if(hasValue(obj)) {
				return false;
			}
		}
		return true;
	}
	
	public static int length(String s){
		if(isEmpty(s)){
			return 0;
		}
		return s.length();
	}
	
	public static int bytesLength(String s){
		if(isEmpty(s)){
			return 0;
		}
		return s.getBytes().length;
	}
	
	public static int charLength(String s){
		if(isEmpty(s)){
			return 0;
		}
		return s.getBytes().length;
	}
	
	public static String leftPad(Object s, char c, int length){
		return pad(s, c, length, true);
	}
	
	public static String rightPad(Object s, char c, int length){
		return pad(s, c, length, false);
	}


	public static String pad(Object s, char c, int length, boolean left){
		StringBuilder str = new StringBuilder(getValue(s));
		while(str.length() < length){
			if(left){
				str.insert(0, c);
			}else {
				str.append(c);
			}
		}
		return str.toString();
	}
	
	public static String substring(String s, int length){
		if(hasValue(s) && s.length() > length){
			return s.substring(0, length);
		}
		return s;
	}
	
	public static boolean isEqual(String s1, String s2){
        return s1 != null && s1.equals(s2);
    }
	
	public static boolean isEqualIgnoreCase(String s1, String s2){
        return s1 != null && s1.equalsIgnoreCase(s2);
    }

	public static String getValue(String s){
		if(s == null){
			return "";
		}
		return s.trim();
	}
	
	public static String getValue(Object o){
		if(o == null || "null".equalsIgnoreCase(o.toString().trim())){
			return "";
		}
		return o.toString().trim();
	}

	public static String getHead(String s, int length) {
		if(length == 0){
			return "";
		}
		if(s == null || s.length() < length) {
			return s;
		}
		return s.substring(0, length);
	}
	
	public static String getTail(String s, int length) {
		if(length == 0){
			return "";
		}
		if(s == null || s.length() < length) {
			return s;
		}
		return s.substring(s.length()-length);
	}
	
	public static String decideValue(String... strs){
		if(strs == null) {
			return null;
		}
        for (String str : strs) {
            if (hasValue(str)) {
                return str;
            }
        }
		return null;
	}

	public static String replaceText(String text, String regex, String replacement) {
		if(text == null) {
			return null;
		}
		if(!regex.contains("$")) {
			return text.replaceAll(regex, replacement);
		}
		String newRegex = regex.replaceAll("\\$", "REGEX_CHAR_DOLLAR");
		String newText = text.replaceAll(newRegex, replacement);
		return newText.replaceAll("REGEX_CHAR_DOLLAR", "\\$");
	}

	public static String bytesToHexStr(byte[] b) {
		if(b == null){
			return null;
		}
		return bytesToHexStr(b, 0, b.length);
	}

	public static String bytesToHexStr(byte[] b, int start, int len) {
		StringBuilder str = new StringBuilder();
		for (int i = start; i < start + len; i++) {
			str.append(String.format("%02x", b[i]));
		}
		return str.toString();
	}

	public static byte[] hexStrToBytes(String str) {
		if (str.length() % 2 != 0) {
			str = "0" + str;
		}
		byte[] temp = new byte[str.length() / 2];
		for (int i = 0; i < str.length(); i += 2) {
			temp[(i / 2)] = ((byte) (Byte.parseByte(str.substring(i, i + 1), 16) * 16
					+ Byte.parseByte(str.substring(i + 1, i + 2), 16)));
		}
		return temp;
	}

	
	public static int toInt(String s){
		if(isEmpty(s)){
			return 0;
		}
		try{
			return Integer.parseInt(s.trim());
		}catch (Exception e) {
			log.error("", e);
		}
		return 0;
	}
	
	public static long toLong(String s){
		if(isEmpty(s)){
			return 0;
		}
		try{
			return Long.parseLong(s.trim());
		}catch (Exception e) {
			log.error("", e);
		}
		return 0;
	}
	
	public static double toDouble(String s){
		if(isEmpty(s)){
			return 0;
		}
		try{
			return Double.parseDouble(s.trim());
		}catch (Exception e) {
			log.error("", e);
		}
		return 0;
	}
	
	public static boolean toBoolean(String s){
		if(isEmpty(s)){
			return false;
		}
		s = s.trim();
        return "true".equalsIgnoreCase(s) || "1".equalsIgnoreCase(s)
                || "y".equalsIgnoreCase(s) || "yes".equalsIgnoreCase(s);
    }
	
	public static String underscoreToCamel(String str){
		if(str == null){
			return "";
		}
		if(!str.contains("_")){
			return str;
		}
		String temp = str.trim().toLowerCase();
		StringBuilder sb = new StringBuilder();
		boolean isUnder = false;
		for(int i=0; i<temp.length(); i++){
			char c = temp.charAt(i);
			if(c == '_'){
				isUnder = true;
				continue;
			}
			if(isUnder){
				sb.append(Character.toUpperCase(c));
				isUnder = false;
			}else{
				sb.append(c);
			}
		}
		return sb.toString();
	}

	public static String camelToUnderscore(String str){
		if(isEmpty(str)){
			return "";
		}
		StringBuilder sb = new StringBuilder();
		for(int i=0; i<str.length(); i++){
			char c = str.charAt(i);
			if(Character.isUpperCase(c)){
				if(i != 0){
					sb.append("_");
				}
				sb.append(Character.toLowerCase(c));
			}else{
				sb.append(c);
			}
		}
		return sb.toString();
	}
	
	public static String upperFirst(String str){
		if(isEmpty(str)){
			return "";
		}
		String f = str.substring(0, 1);
		return f.toUpperCase() + str.substring(1);
	}
	
	public static String lowerFirst(String str){
		if(isEmpty(str)){
			return "";
		}
		String f = str.substring(0, 1);
		return f.toLowerCase()+str.substring(1);
	}
	
	public static String toString(List<?> list){
		return toString(list, ";");
	}
	
	public static String toString(Object[] strArray){
		return toString(Arrays.asList(strArray), ";");
	}
	
	public static String toString(List<?> list, String delimiter){
		StringJoiner join = new StringJoiner("\n");
		for(int i=0; list!=null && i<list.size(); i++){
			join.add(toString(list.get(i)));
		}
		return join.toString();
	}
	
	public static String toString(Object o){
		return getValue(o);
	}
	
	public static String maxLength(String s, int maxLength) {
		if(s == null) {
			return  "";
		}
		if(s.length() > maxLength) {
			return s.substring(0, maxLength-3) + "...";
		}
		return s;
	}
	
	/**
	 * base on java8
	 */
	public static String encodeBase64(byte[] bytes){
		return Base64.getEncoder().encodeToString(bytes);
	}

	/**
	 * base on java8
	 */
	public static byte[] decodeBase64(String str){
		return Base64.getDecoder().decode(str);
	}
	
	/**
	 * base on java8
	 */
	public static String encodeMimeBase64(byte[] bytes){
		return Base64.getMimeEncoder().encodeToString(bytes);
	}

	/**
	 * base on java8
	 */
	public static byte[] decodeMimeBase64(String str){
		return Base64.getMimeDecoder().decode(str);
	}
	
	public static String unicodeDecode(String unicode){  
		if(isEmpty(unicode)){
			return unicode;
		}
		StringBuilder sb = new StringBuilder();
		int i;
		int pos = 0;
		while((i = unicode.indexOf("\\u", pos)) != -1){
			sb.append(unicode, pos, i);
			if(i+5 < unicode.length()){  
				pos = i+6;
				sb.append((char)Integer.parseInt(unicode.substring(i+2, i+6), 16));
			}  
		}  
		return sb.toString();
	}
	
	public static String unicodeEncode(String string) {
		if(isEmpty(string)){
			return string;
		}
		StringBuilder unicode = new StringBuilder();
		for (int i = 0; i < string.length(); i++) {
			char c = string.charAt(i);
			unicode.append("\\u").append(Integer.toHexString(c));
		}
		return unicode.toString();
	}
}
